/*
 *
 * 名称：九宫
 * 功能：奇门遁甲九宫运转逻辑
 * 作者：清河张
 * 时间：2025.05.11
 *
 */

#ifndef QMGONG9_H
#define QMGONG9_H
#include <QByteArray>
#include "qmdef.h"
#include "base/shuzi.h"
#include "base/wuxing.h"
#include "base/gua8.h"
#include "base/gua64.h"
#include "qmxing9.h"
#include "men8.h"
#include "shen8.h"
#include "base/bazi.h"
#include "base/lifa.h"
#include "base/gong9.h"

namespace QMDJ {

class QMGONG9//奇门九宫
{
public:

    enum MASK : quint64
    {
        MASK_MENPO          = 1 << 0,//门迫

        MASK_RUMU1          = 1 << 4,//地盘入墓
        MASK_RUMU2          = 1 << 5,//天盘入墓
        MASK_JIXING1        = 1 << 6,//地盘击刑
        MASK_JIXING2        = 1 << 7,//天盘击刑
        MASK_KONGWANG1      = 1 << 8,//地支一空亡
        MASK_KONGWANG2      = 1 << 9,//地支二空亡
        MASK_MAXING1        = 1 << 10,//地支一马星
        MASK_MAXING2        = 1 << 11,//地支二马星

        GANMASK1 = MASK_RUMU1 | MASK_JIXING1,//地盘干见鬼
        GANMASK2 = MASK_RUMU2 | MASK_JIXING2,//天盘干见鬼

        ZHIMASK1 = MASK_KONGWANG1 | MASK_MAXING1,//地支一见鬼
        ZHIMASK2 = MASK_KONGWANG2 | MASK_MAXING2,//地支二见鬼

    };

    struct GONG : public XZGONG
    {
        struct{
            const int _q3y6 : 5;//三奇六仪
            const int ____ : 27;//备用，对齐
        };

        GONG(const XZGONG&, QMGONG9*, int, const char*);

        void qing_paipan();//清排盘
        void qing_neiguan();//清内观
        void addmask(quint64);//加标记
        void rmmask(quint64);//去标记
        bool hasmask(quint64);//判断存在标记

        WUXING5::WXXQS wxxqs() const;//宫的旺相休囚死状态

        void shengxiangyi();//生象意
        void neiguan();//清内观
        void jiexi();//宫解，评论

        void maxing_he(int);//马星如何
        void kongwang_he(ZHI12X2 kw);//空亡如何
        void mp_hu();//击刑乎
        void rm_hu();//入墓乎
        void yin_an_he();//隐干暗干如何
        void jx_hu();//击刑乎

        const char* gongname() const;//宫号数字名
        const char* name() const;//宫名

        GONG * ji0();//寄出地盘
        GONG * ji1();//寄出天盘
        GONG * fei(int jb);//飞宫
        GONG * xiantian();//找先天八卦，飘宫
        GONG * houtian();//找后天八卦，挖宫

        QMGONG9* const _g9;//九宫指针
        const char* _name;//宫名
        quint64 _mask;//异常标志
        MEN8 _men;//门
        XING9 _xing;//星
        SHEN8 _shen;//神
        GAN10 _dp, _tp, _yin, _an;//地盘干、天盘干、隐干、暗干
        WUXING5::WXXQS _wxxqs;//宫的能级
        QByteArray _yongshenming;//用神
        QByteArray _beizhu;//备注
        QByteArray _xiangyi, _jiexi;//象意，解析
        QString _jumian;//局面
    };

    QMGONG9(PARAS& paras);

    GONG* teshu(int ts);//找对应宫
    GONG* teshu(int ts, const BAZI&);//找对应宫
    GONG* zhuan(int jd);//寄居宫转运jd个宫
    GONG * mx();//查找

    GONG* gzhi(int z);//找地支
    GONG* zhg();//中宫
    GONG *xu(int x);//序号找宫
    GONG *gong(int g);//宫号找宫
    GONG *gua1(int g);//先天卦找宫
    GONG *gua2(int g);//后天卦找宫

    void neiguan();//内观

    void ji4jiju(int j4);//按四季将中宫寄居

    void gongjiju(int g);//中宫寄居到g宫

    int jd() const;//转盘奇门旋转过角度

    //转布，M为元素类型，N为指定元素值列表
    template< class M, class N = M>
    void zhuanbu(M GONG::* m, int num = 9, int order_start = 0, int dw = 1, N value[9] = nullptr)//转布
    {
        int order;
        if(value)
        {
            for(int i = 0; i < num; ++i)
            {
                order = XUNHUAN ( order_start + dw*i, num );
                _gongs[::gong9_xu_gid(order)].*m = value[i];
            }
        }else{
            for(int i = 0; i < num; ++i)
            {
                order = XUNHUAN ( order_start + dw*i, num  );
                _gongs[::gong9_xu_gid(order)].*m = (N)i;
            }
        }
    }

    //转动，指定元素m转动jd次
    template< class M>
    void zhuandong(M GONG::* m, int jd)//转动元素
    {
        int order;
        M tmp[8];

        for(int i = 0; i < 8; ++i)
        {
            order = XUNHUAN ( i + jd, 8 );
            tmp[order] = _gongs[::gong9_xu_gid(i)].*m;
        }

        for(int i = 0; i < 8; ++i)
        {
            _gongs[::gong9_xu_gid(i)].*m = tmp[i];
        }
    }

    //飞布，元素m默认从0宫开始，每次飞1宫，dw<0会逆飞
    void feibu(GAN10 GONG::* m, int gong_start = 0, int dw = 1);

    //飞动，指定元素飞jb次，jb<0为逆飞
    template< class M>
    void feidong(M GONG::* m, int jb)//飞动
    {
        int g;
        M tmp[9];

        for(int i = 0; i < 9; ++i)
        {
            g = XUNHUAN ( i + jb, 9 );
            tmp[g] = _gongs[i].*m;
        }

        for(int i = 0; i < 9; ++i)
        {
            _gongs[i].*m = tmp[i];
        }
    }

    //查找，元素m值为v的宫
    template< class M, class N>
    GONG * chazhao(M GONG::* m, N v)
    {
        GONG * gong = nullptr;

        for(int i = 0; i < 9; ++i)
        {
            if(_gongs[i].*m == v)
            {
                gong = &_gongs[i];
                break;
            }
        }

        return gong;
    }

    //定局方式，张氏/茅山/拆补/置闰/阴盘/指定
    enum DINGJUFA{ ZHANGSHI, MAOSHAN, CHAIBU, ZHIRUN, YINPAN, ZHIDING };

    //起局前传入时间
    void prepare(const LIFA& ln);

    //根据用神属性找宫位
    GONG* yongshen(unsigned buluo, int bianhao, const BAZI& ms,
                   const QByteArray& ming, QByteArray& bianzhi, QByteArray& nengji);

    //设置方案
    void shezhifangan(const QJsonObject &&jsonGeJu,
                      const QJsonObject &&jsonXingGong);

    //清理排盘
    void reset();

    //初断
    const QByteArray& chuduan();

    //局面
    QString jumian() const;

    //年家入口
    void nianjia( int& ju, int& yy, GAN10& qi, GAN10& luo);
    //月家入口
    void yuejia( int& ju, int& yy, GAN10& qi, GAN10& luo);
    //日家入口
    void rijia( int& ju, int& yy, GAN10& qi, GAN10& luo);
    //时家入口
    void shijia( int& ju, int& yy, GAN10& qi, GAN10& luo);
private:

    int shijia_paipan(int, int, const GANZHI& gz, GAN10&, GAN10&);//时家盘
    int yuejia_paipan(int, int, const GANZHI& gz, GAN10&, GAN10&);//时家盘
    int rijia_paipan(int, int, const GANZHI& gz, GAN10&, GAN10&);//时家盘

    //除“指定”起局方式外，计算局数
    int maoshanyuan(JIE24&);
    int chaibuyuan(JIE24&);
    int zhirunyuan(JIE24&);
    int zhangshiyuan(JIE24&);
    int yinpan(JIE24&);

    //年家定局
    int nianjiadingju() const;
    //月家定局
    int yuejiadingju() const;
    //日家定局
    int rijiadingju() const;
    //时家定局
    int shijiadingju(int, int, int) const;

    //查对应的三奇六仪
    int chazhao3q6y(GAN10) const;

    GONG _gongs[9];//奇门宫
    PARAS& _paras;//参数

    //地盘/天盘寄居宫
    GONG* _jiju1;
    GONG* _jiju2;

    //马星/值符/值使宫位
    GONG* _mx;
    GONG* _zf;
    GONG* _zs;

    bool _yy;//阴遁阳看过
    int _jd;//转盘角度
    LIFA _lf;//起局时间的历法
    BAZI _bz;//起局时的八字

    QByteArray _jxstr;//解析器
    QByteArray _xinggong[9][9];//星宫象意
    QByteArray _geju[10][10];//格局象意
};

};


#endif // QMGONG9_H
